/**
 *******************************************************************************
 * @file  ev_hc32f4a0_lqfp176.c
 * @brief This file provides firmware functions for EV_HC32F4A0_LQFP176 BSP
 @verbatim
   Change Logs:
   Date             Author          Notes
   2020-06-12       Zhangxl         First version
   2020-07-15       Zhangxl         Use XTAL 8MHz as PLL source
   2020-08-25       Zhangxl         Modify for MISRAC2012-14.3, 14.4
   2020-08-28       Zhangxl         1. Refine API function: BSP_LCD_BKLCmd
                                    2. Add LCD backlight port macro-define
                                    3. Add doxygen group for local functions
   2020-09-27       Zhangxl         Set CT reset pin to input state for solving conflict
   2020-10-30       Zhangxl         1. Set IOEXP IC reset pin to NMOS output
                                    2. Use new I2C API
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by HDSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "ev_hc32f4a0_lqfp176.h"
#include "ev_hc32f4a0_lqfp176_tca9539.h"

/**
 * @defgroup BSP BSP
 * @{
 */

/**
 * @defgroup EV_HC32F4A0_LQFP176 HC32F4A0_LQFP176_EVB
 * @{
 */

#if (BSP_EV_HC32F4A0_LQFP176 == BSP_EV_HC32F4A0)

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/
/**
 * @defgroup BSP_Local_Macros BSP Local Macros
 * @{
 */
#define LCD_BKL_PORT                (GPIO_PORT_I)
#define LCD_BKL_PIN                 (GPIO_PIN_00)
/**
 * @}
 */

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/
/**
 * @addtogroup BSP_Local_Functions
 * @{
 */
static void BSP_I2C_Init(void);
static void BSP_KEY_ROW0_IrqCallback(void);
static void BSP_KEY_ROW1_IrqCallback(void);
static void BSP_KEY_ROW2_IrqCallback(void);
static void BSP_KEY_ROW0_Init(void);
static void BSP_KEY_ROW1_Init(void);
static void BSP_KEY_ROW2_Init(void);
static void BSP_KEY_COL_Init(void);
/**
 * @}
 */

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/
/**
* @defgroup BSP_Local_Variables BSP Local Variables
* @{
*/
static uint32_t gu32GlobalKey = 0x00000000UL;
/**
 * @}
 */

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
/**
 * @defgroup BSP_Global_Functions BSP Global Functions
 * @{
 */

/**
 * @brief  EIO delay
 * @param  [in] u32Delay Delay in ms
 * @retval none
 */
void EIO_Delay(uint32_t u32Delay)
{
    DDL_DelayMS(u32Delay);
}

/**
 * @brief  EIO initialize
 * @param  None
 * @retval None
 */
void EIO_Init(void)
{
    BSP_I2C_Init();
}

/**
 * @brief  EIO register write
 * @param  [in] u8Reg register definition
 *   @arg  TCA9539_REG_INPUT_0
 *   @arg  TCA9539_REG_INPUT_1
 *   @arg  TCA9539_REG_OUTPUT_0
 *   @arg  TCA9539_REG_OUTPUT_1
 *   @arg  TCA9539_REG_INVERT_0
 *   @arg  TCA9539_REG_INVERT_1
 *   @arg  TCA9539_REG_CONFIG_0
 *   @arg  TCA9539_REG_CONFIG_1
 * @param  [in] u8Val register value
 * @retval None
 */
void EIO_Write(uint8_t u8Reg, uint8_t u8Val)
{
    (void)I2C_Start(TCA9539_I2C_CH, TCA9539_TIMEOUT);
    (void)I2C_TransAddr(TCA9539_I2C_CH, TCA9539_ADDR, BSP_I2C_WR, TCA9539_TIMEOUT);
    (void)I2C_TransData(TCA9539_I2C_CH, (uint8_t *)&u8Reg, 1UL, TCA9539_TIMEOUT);
    (void)I2C_TransData(TCA9539_I2C_CH, (uint8_t *)&u8Val, 1UL, TCA9539_TIMEOUT);
    (void)I2C_Stop(TCA9539_I2C_CH, TCA9539_TIMEOUT);
}

/**
 * @brief  EIO register read
 * @param  [in] u8Reg register definition
 *   @arg  TCA9539_REG_INPUT_0
 *   @arg  TCA9539_REG_INPUT_1
 *   @arg  TCA9539_REG_OUTPUT_0
 *   @arg  TCA9539_REG_OUTPUT_1
 *   @arg  TCA9539_REG_INVERT_0
 *   @arg  TCA9539_REG_INVERT_1
 *   @arg  TCA9539_REG_CONFIG_0
 *   @arg  TCA9539_REG_CONFIG_1
 * @param  [out] *u8Val register value
 * @retval None
 */
void EIO_Read(uint8_t u8Reg, uint8_t *u8Val)
{
    (void)I2C_Start(TCA9539_I2C_CH, TCA9539_TIMEOUT);
    (void)I2C_TransAddr(TCA9539_I2C_CH, TCA9539_ADDR, BSP_I2C_WR, TCA9539_TIMEOUT);
    (void)I2C_TransData(TCA9539_I2C_CH, (uint8_t *)&u8Reg, 1UL, TCA9539_TIMEOUT);

    (void)I2C_Restart(TCA9539_I2C_CH, TCA9539_TIMEOUT);
    /* Config NACK if only read one data */
    (void)I2C_AckConfig(TCA9539_I2C_CH, I2C_NACK);

    (void)I2C_TransAddr(TCA9539_I2C_CH, TCA9539_ADDR, BSP_I2C_RD, TCA9539_TIMEOUT);
    (void)I2C_MasterReceiveAndStop(TCA9539_I2C_CH, u8Val, 1UL, TCA9539_TIMEOUT);
}

/**
 * @brief  EIO reset
 * @retval none
 */
void EIO_Reset(void)
{
    stc_gpio_init_t stcGpioInit;
    (void)GPIO_StructInit(&stcGpioInit);
    /* Set to NMOS output */
    stcGpioInit.u16PinOType = PIN_OTYPE_NMOS;
    (void)GPIO_Init(EIO_RST_PORT, EIO_RST_PIN, &stcGpioInit);

    GPIO_OE(EIO_RST_PORT, EIO_RST_PIN, Enable);
    GPIO_ResetPins(EIO_RST_PORT, EIO_RST_PIN);
    DDL_DelayMS(3UL);
    GPIO_SetPins(EIO_RST_PORT, EIO_RST_PIN);
}

/**
  * @brief  EIO interrupt initialize
  * @retval none
  */
void EIO_IntInit(void)
{
    /* interrupt config*/
}

/**
 * @brief  BSP clock initialize.
 *         Set board system clock to PLLH@240MHz
 *         Flash: 5 wait
 *         SRAM_HS: 1 wait
 *         SRAM1_2_3_4_B: 2 wait
 *         PCLK0: 240MHz
 *         PCLK1: 120MHz
 *         PCLK2: 60MHz
 *         PCLK3: 60MHz
 *         PCLK4: 120MHz
 *         EXCLK: 120MHz
 *         HCLK:  240MHz
 * @param  None
 * @retval None
 */
void BSP_CLK_Init(void)
{
    stc_clk_xtal_init_t stcXtalInit;
    stc_clk_pllh_init_t stcPLLHInit;

    /* PCLK0, HCLK  Max 240MHz */
    /* PCLK1, PCLK4 Max 120MHz */
    /* PCLK2, PCLK3 Max 60MHz  */
    /* EX BUS Max 120MHz */
    CLK_ClkDiv(CLK_CATE_ALL,                                                   \
               (CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 |             \
                CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 |             \
                CLK_HCLK_DIV1));

    CLK_XtalStructInit(&stcXtalInit);
    /* Config Xtal and enable Xtal */
    stcXtalInit.u8XtalMode = CLK_XTALMODE_OSC;
    stcXtalInit.u8XtalDrv = CLK_XTALDRV_LOW;
    stcXtalInit.u8XtalState = CLK_XTAL_ON;
    stcXtalInit.u8XtalStb = CLK_XTALSTB_2MS;
    CLK_XtalInit(&stcXtalInit);

    (void)CLK_PLLHStructInit(&stcPLLHInit);
    /* VCO = (8/1)*120 = 960MHz*/
    stcPLLHInit.u8PLLState = CLK_PLLH_ON;
    stcPLLHInit.PLLCFGR = 0UL;
    stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLN = 120UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL;
    stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLLSRC_XTAL;
    (void)CLK_PLLHInit(&stcPLLHInit);

    /* Highspeed SRAM set to 1 Read/Write wait cycle */
    SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE_1, SRAM_WAIT_CYCLE_1);

    /* SRAM1_2_3_4_backup set to 2 Read/Write wait cycle */
    SRAM_SetWaitCycle((SRAM_SRAM123 | SRAM_SRAM4 | SRAM_SRAMB), SRAM_WAIT_CYCLE_2, SRAM_WAIT_CYCLE_2);

    /* 0-wait @ 40MHz */
    EFM_SetWaitCycle(EFM_WAIT_CYCLE_5);

    /* 4 cycles for 200 ~ 250MHz */
    GPIO_SetReadWaitCycle(GPIO_READ_WAIT_4);

    CLK_SetSysClkSrc(CLK_SYSCLKSOURCE_PLLH);
}

/**
 * @brief  CAM initialize.
 * @param  None
 * @retval none
 */
void BSP_CAM_IO_Init(void)
{
    /* Init camera and touch panel control IO before direction setting */
    BSP_IO_WritePortPin(CAM_PORT, (CAM_RST_PIN | CAM_STB_PIN), EIO_PIN_RESET);
    /* CAM pins set to output */
    BSP_IO_ConfigPortPin(CAM_PORT, (CAM_RST_PIN | CAM_STB_PIN), EIO_DIR_OUT);
}

/**
 * @brief  CAM reset pin config.
 * @param  [in] Cmd
 *   @arg  EIO_PIN_SET
 *   @arg  EIO_PIN_RESET
 * @retval none
 */
void BSP_CAM_RSTCmd(uint8_t Cmd)
{
    BSP_IO_WritePortPin(CAM_PORT, CAM_RST_PIN, Cmd);
}

/**
 * @brief  CAM standby pin config.
 * @param  [in] Cmd
 *   @arg  EIO_PIN_SET
 *   @arg  EIO_PIN_RESET
 * @retval none
 */
void BSP_CAM_STBCmd(uint8_t Cmd)
{
    BSP_IO_WritePortPin(CAM_PORT, CAM_STB_PIN, Cmd);
}

/**
 * @brief  CAN PYH STB pin initialization.
 * @param  None
 * @retval none
 */
void BSP_CAN_STB_IO_Init(void)
{
    /* Set STB pin high before output */
    BSP_IO_WritePortPin(CAN_STB_PORT, CAN_STB_PIN, EIO_PIN_SET);
    /* STB pin set to output */
    BSP_IO_ConfigPortPin(CAN_STB_PORT, CAN_STB_PIN, EIO_DIR_OUT);
}

/**
 * @brief  CAN PYH STB pin control
 * @param  [in] Cmd
 *   @arg  EIO_PIN_SET
 *   @arg  EIO_PIN_RESET
 * @retval none
 */
void BSP_CAN_STBCmd(uint8_t Cmd)
{
    BSP_IO_WritePortPin(CAN_STB_PORT, CAN_STB_PIN, Cmd);
}

/**
 * @brief  Cap panel reset pin config.
 * @param  [in] Cmd
 *   @arg  EIO_PIN_SET
 *   @arg  EIO_PIN_RESET
 * @retval none
 */
void BSP_CT_RSTCmd(uint8_t Cmd)
{
    BSP_IO_ConfigPortPin(LCD_CTRST_PORT, LCD_CTRST_PIN, EIO_DIR_OUT);
    BSP_IO_WritePortPin(LCD_CTRST_PORT, LCD_CTRST_PIN, Cmd);
    BSP_IO_ConfigPortPin(LCD_CTRST_PORT, LCD_CTRST_PIN, EIO_DIR_IN);
}

/**
 * @brief  LCD ctrl IO initialize.
 * @param  None
 * @retval none
 */
void BSP_LCD_IO_Init(void)
{
    /* Init LCD backlight IO */
    GPIO_OE(LCD_BKL_PORT, LCD_BKL_PIN, Enable);

    /* Init LCD and touch panel control IO before direction setting */
    BSP_IO_WritePortPin(LCD_RST_PORT, LCD_RST_PIN, EIO_PIN_SET);
    BSP_IO_WritePortPin(LCD_CTRST_PORT, LCD_CTRST_PIN, EIO_PIN_RESET);

    /* LCD and touch panel control IO set to output */
    BSP_IO_ConfigPortPin(LCD_RST_PORT, LCD_RST_PIN, EIO_DIR_OUT);
    BSP_IO_ConfigPortPin(LCD_CTRST_PORT, LCD_CTRST_PIN, EIO_DIR_OUT);

    DDL_DelayMS(100UL);
    BSP_IO_WritePortPin(LCD_CTINT_PORT, LCD_CTINT_PIN, EIO_PIN_RESET);
    BSP_IO_ConfigPortPin(LCD_CTINT_PORT, LCD_CTINT_PIN, EIO_DIR_OUT);
    DDL_DelayMS(100UL);
    BSP_IO_WritePortPin(LCD_CTRST_PORT, LCD_CTRST_PIN, EIO_PIN_SET);
    DDL_DelayMS(100UL);
    BSP_IO_ConfigPortPin(LCD_CTRST_PORT, LCD_CTRST_PIN, EIO_DIR_IN);
    BSP_IO_ConfigPortPin(LCD_CTINT_PORT, LCD_CTINT_PIN, EIO_DIR_IN);
}

/**
 * @brief  LCD reset pin config.
 * @param  [in] Cmd
 *   @arg  EIO_PIN_SET
 *   @arg  EIO_PIN_RESET
 * @retval none
 */
void BSP_LCD_RSTCmd(uint8_t Cmd)
{
    BSP_IO_WritePortPin(LCD_RST_PORT, LCD_RST_PIN, Cmd);
}

/**
 * @brief  LCD backlight pin config.
 * @param  [in] Cmd
 *   @arg  EIO_PIN_SET
 *   @arg  EIO_PIN_RESET
 * @retval none
 */
void BSP_LCD_BKLCmd(uint8_t Cmd)
{
    if (EIO_PIN_SET == Cmd)
    {
        GPIO_SetPins(LCD_BKL_PORT, LCD_BKL_PIN);
    }
    else
    {
        GPIO_ResetPins(LCD_BKL_PORT, LCD_BKL_PIN);
    }
}

/**
 * @brief  LED initialize.
 * @param  None
 * @retval none
 */
void BSP_LED_Init(void)
{
    /* Turn off LED before output */
    BSP_IO_WritePortPin(LED_PORT, (LED_RED_PIN | LED_YELLOW_PIN | LED_BLUE_PIN), LED_OFF);
    /* LED pins set to output */
    BSP_IO_ConfigPortPin(LED_PORT, (LED_RED_PIN | LED_YELLOW_PIN |LED_BLUE_PIN), EIO_DIR_OUT);
}

/**
 * @brief  Turn on LEDs.
 * @param  [in] u8Led LED
 *   @arg  LED_RED
 *   @arg  LED_YELLOW
 *   @arg  LED_BLUE
 * @retval none
 */
void BSP_LED_On(uint8_t u8Led)
{
    BSP_IO_WritePortPin(LED_PORT, u8Led, LED_ON);
}

/**
 * @brief  Turn off LEDs.
 * @param  [in] u8Led LED
 *   @arg  LED_RED
 *   @arg  LED_YELLOW
 *   @arg  LED_BLUE
 * @retval none
 */
void BSP_LED_Off(uint8_t u8Led)
{
    BSP_IO_WritePortPin(LED_PORT, u8Led, LED_OFF);
}

/**
 * @brief  Toggle LEDs.
 * @param  [in] u8Led LED
 *   @arg  LED_RED
 *   @arg  LED_YELLOW
 *   @arg  LED_BLUE
 * @retval none
 */
void BSP_LED_Toggle(uint8_t u8Led)
{
    BSP_IO_TogglePortPin(LED_PORT, u8Led);
}

/**
 * @brief  BSP printf port initialize
 * @param  None
 * @retval None
 */
void BSP_PRINTF_PortInit(void)
{
    GPIO_SetFunc(BSP_PRINTF_PORT, BSP_PRINTF_PIN, BSP_PRINTF_PORT_FUNC, PIN_SUBFUNC_DISABLE);
}

/**
 * @brief  BSP key initialize
 * @param  None
 * @retval None
 */
void BSP_KEY_Init(void)
{
    BSP_KEY_ROW0_Init();
    BSP_KEY_ROW1_Init();
    BSP_KEY_ROW2_Init();

    BSP_KEY_COL_Init();

    /* Clear all KEYIN interrupt flag before enable */
    EXINT_ClrExIntSrc(BSP_KEY_ROW0_EXINT);
    EXINT_ClrExIntSrc(BSP_KEY_ROW1_EXINT);
    EXINT_ClrExIntSrc(BSP_KEY_ROW2_EXINT);

    KEYSCAN_Cmd(Enable);
}

/**
 * @brief  Get BSP key status
 * @param  [in] u32Key chose one macro from below
 *   @arg  BSP_KEY_1
 *   @arg  BSP_KEY_2
 *   @arg  BSP_KEY_3
 *   @arg  BSP_KEY_4
 *   @arg  BSP_KEY_5
 *   @arg  BSP_KEY_6
 *   @arg  BSP_KEY_7
 *   @arg  BSP_KEY_8
 *   @arg  BSP_KEY_9
 * @retval en_flag_status_t
 *   @arg  Set, Key pressed.
 *   @arg  Reset, Key released.
 */
en_flag_status_t BSP_KEY_GetStatus(uint32_t u32Key)
{
    en_flag_status_t enRet = Reset;
    if (0UL != (gu32GlobalKey & u32Key))
    {
        enRet = Set;
        gu32GlobalKey &= ~u32Key;
    }
    else
    {
    }
    return enRet;
}

/**
 * @}
 */

/**
 * @defgroup BSP_Local_Functions BSP Local Functions
 * @{
 */

/**
 * @brief  BSP I2C initialize
 * @param  None
 * @retval None
 */
static void BSP_I2C_Init(void)
{
    float32_t fErr;
    stc_i2c_init_t stcI2cInit;
    stc_gpio_init_t stcGpioInit;
    uint8_t i;

    static en_flag_status_t enI2CActivateFlag = Reset;

    if (Reset == enI2CActivateFlag)
    {
        (void)GPIO_StructInit(&stcGpioInit);

        /* */
        (void)GPIO_Init(BSP_I2C_SCL_PORT, BSP_I2C_SCL_PIN, &stcGpioInit);
        (void)GPIO_Init(BSP_I2C_SDA_PORT, BSP_I2C_SDA_PIN, &stcGpioInit);

        GPIO_SetFunc(BSP_I2C_SCL_PORT, BSP_I2C_SCL_PIN, BSP_I2C_SCL_GPIO_FUNC ,PIN_SUBFUNC_DISABLE);
        GPIO_SetFunc(BSP_I2C_SDA_PORT, BSP_I2C_SDA_PIN, BSP_I2C_SDA_GPIO_FUNC ,PIN_SUBFUNC_DISABLE);

        EIO_Reset();

        /* I2C1 clock enable */
        PWC_Fcg1PeriphClockCmd(BSP_I2C_FCG, Enable);

        I2C_DeInit(BSP_I2C_CH);

        (void)I2C_StructInit(&stcI2cInit);
        stcI2cInit.u32Baudrate = BSP_I2C_BAUDRATE;
        stcI2cInit.u32SclTime = 0U;
        stcI2cInit.u32ClkDiv = I2C_CLK_DIV16;
        for (i = 0U; i < 5U; i++)
        {
            if(Ok != I2C_Init(BSP_I2C_CH, &stcI2cInit, &fErr))
            {
                stcI2cInit.u32ClkDiv--;
            }
            else
            {
                break;
            }
        }

        I2C_Cmd(BSP_I2C_CH, Enable);

        enI2CActivateFlag = Set;
    }
}

/**
 * @brief  EXINT Ch.8 as BSP Key row 0 callback function
 * @param  None
 * @retval None
 */
static void BSP_KEY_ROW0_IrqCallback(void)
{
    const uint32_t u32Idx = KEYSCAN_GetKeyoutIdx();
    if (Set == EXINT_GetExIntSrc(BSP_KEY_ROW0_EXINT))
    {
        for (;;)
        {
            if (Pin_Reset == GPIO_ReadInputPins(BSP_KEYIN0_PORT, BSP_KEYIN0_PIN))
            {
                gu32GlobalKey |= (0x01UL) << u32Idx;
            }
            else
            {
                /* clear int request flag  after KEY released */
                EXINT_ClrExIntSrc(BSP_KEY_ROW0_EXINT);
                break;
            }
        }
    }
}

/**
 * @brief  EXINT Ch.3 as BSP Key row 1 callback function
 * @param  None
 * @retval None
 */
static void BSP_KEY_ROW1_IrqCallback(void)
{
    const uint32_t u32Idx = KEYSCAN_GetKeyoutIdx();
    if (Set == EXINT_GetExIntSrc(BSP_KEY_ROW1_EXINT))
    {
        for (;;)
        {
            if (Pin_Reset == GPIO_ReadInputPins(BSP_KEYIN1_PORT, BSP_KEYIN1_PIN))
            {
                gu32GlobalKey |= (0x10UL) << u32Idx;
            }
            else
            {
                /* clear int request flag after KEY released */
                EXINT_ClrExIntSrc(BSP_KEY_ROW1_EXINT);
                break;
            }
        }
    }
}

/**
 * @brief  EXINT Ch.7 as KYESCAN row 2 callback function
 * @param  None
 * @retval None
 */
static void BSP_KEY_ROW2_IrqCallback(void)
{
    const uint32_t u32Idx = KEYSCAN_GetKeyoutIdx();
    if (Set == EXINT_GetExIntSrc(BSP_KEY_ROW2_EXINT))
    {
        for (;;)
        {
            if (Pin_Reset == GPIO_ReadInputPins(BSP_KEYIN2_PORT, BSP_KEYIN2_PIN))
            {
                gu32GlobalKey |= (0x100UL) << u32Idx;
            }
            else
            {
                /* clear int request flag after KEY released */
                EXINT_ClrExIntSrc(BSP_KEY_ROW2_EXINT);
                break;
            }
        }
    }
}

/**
 * @brief  BSP key row 0 initialize
 * @param  None
 * @retval None
 */
static void BSP_KEY_ROW0_Init(void)
{
    stc_exint_init_t stcExintInit;
    stc_irq_signin_config_t stcIrqSignConfig;
    stc_gpio_init_t stcGpioInit;

    /* GPIO config */
    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16ExInt = PIN_EXINT_ON;
    stcGpioInit.u16PullUp = PIN_PU_ON;
    (void)GPIO_Init(BSP_KEYIN0_PORT, BSP_KEYIN0_PIN, &stcGpioInit);

    /* Exint config */
    (void)EXINT_StructInit(&stcExintInit);
    stcExintInit.u32ExIntCh = BSP_KEY_ROW0_EXINT;
    stcExintInit.u32ExIntLvl= EXINT_TRIGGER_FALLING;
    (void)EXINT_Init(&stcExintInit);

    /* IRQ sign-in */
    stcIrqSignConfig.enIntSrc = BSP_KEY_ROW0_INT_SRC;
    stcIrqSignConfig.enIRQn   = BSP_KEY_ROW0_IRQn;
    stcIrqSignConfig.pfnCallback = &BSP_KEY_ROW0_IrqCallback;
    (void)INTC_IrqSignIn(&stcIrqSignConfig);

    /* NVIC config */
    NVIC_ClearPendingIRQ(BSP_KEY_ROW0_IRQn);
    NVIC_SetPriority(BSP_KEY_ROW0_IRQn,DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_EnableIRQ(BSP_KEY_ROW0_IRQn);
}

/**
 * @brief  BSP key row 1 initialize
 * @param  None
 * @retval None
 */
static void BSP_KEY_ROW1_Init(void)
{
    stc_exint_init_t stcExintInit;
    stc_irq_signin_config_t stcIrqSignConfig;
    stc_gpio_init_t stcGpioInit;

    /* GPIO config */
    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16ExInt = PIN_EXINT_ON;
    stcGpioInit.u16PullUp = PIN_PU_ON;
    (void)GPIO_Init(BSP_KEYIN1_PORT, BSP_KEYIN1_PIN, &stcGpioInit);

    /* Exint config */
    (void)EXINT_StructInit(&stcExintInit);
    stcExintInit.u32ExIntCh = BSP_KEY_ROW1_EXINT;
    stcExintInit.u32ExIntLvl= EXINT_TRIGGER_FALLING;
    (void)EXINT_Init(&stcExintInit);

    /* IRQ sign-in */
    stcIrqSignConfig.enIntSrc = BSP_KEY_ROW1_INT_SRC;
    stcIrqSignConfig.enIRQn   = BSP_KEY_ROW1_IRQn;
    stcIrqSignConfig.pfnCallback = &BSP_KEY_ROW1_IrqCallback;
    (void)INTC_IrqSignIn(&stcIrqSignConfig);

    /* NVIC config */
    NVIC_ClearPendingIRQ(BSP_KEY_ROW1_IRQn);
    NVIC_SetPriority(BSP_KEY_ROW1_IRQn,DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_EnableIRQ(BSP_KEY_ROW1_IRQn);
}

/**
 * @brief  BSP key row 2 initialize
 * @param  None
 * @retval None
 */
static void BSP_KEY_ROW2_Init(void)
{
    stc_exint_init_t stcExintInit;
    stc_irq_signin_config_t stcIrqSignConfig;
    stc_gpio_init_t stcGpioInit;

    /* GPIO config */
    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16ExInt = PIN_EXINT_ON;
    stcGpioInit.u16PullUp = PIN_PU_ON;
    (void)GPIO_Init(BSP_KEYIN2_PORT, BSP_KEYIN2_PIN, &stcGpioInit);

    /* Exint config */
    (void)EXINT_StructInit(&stcExintInit);
    stcExintInit.u32ExIntCh = BSP_KEY_ROW2_EXINT;
    stcExintInit.u32ExIntLvl= EXINT_TRIGGER_FALLING;
    (void)EXINT_Init(&stcExintInit);

    /* IRQ sign-in */
    stcIrqSignConfig.enIntSrc = BSP_KEY_ROW2_INT_SRC;
    stcIrqSignConfig.enIRQn   = BSP_KEY_ROW2_IRQn;
    stcIrqSignConfig.pfnCallback = &BSP_KEY_ROW2_IrqCallback;
    (void)INTC_IrqSignIn(&stcIrqSignConfig);

    /* NVIC config */
    NVIC_ClearPendingIRQ(BSP_KEY_ROW2_IRQn);
    NVIC_SetPriority(BSP_KEY_ROW2_IRQn,DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_EnableIRQ(BSP_KEY_ROW2_IRQn);
}

/**
 * @brief  BSP key column initialize
 * @param  None
 * @retval None
 */
static void BSP_KEY_COL_Init(void)
{
    stc_gpio_init_t stcGpioInit;
    stc_keyscan_init_t stcKeyscanInit;

    (void)GPIO_StructInit(&stcGpioInit);
    (void)KEYSCAN_StructInit(&stcKeyscanInit);

    (void)GPIO_Init(BSP_KEYOUT0_PORT, BSP_KEYOUT0_PIN, &stcGpioInit);
    GPIO_SetFunc(BSP_KEYOUT0_PORT, BSP_KEYOUT0_PIN, GPIO_FUNC_8_KEYSCAN, PIN_SUBFUNC_DISABLE);

    (void)GPIO_Init(BSP_KEYOUT1_PORT, BSP_KEYOUT1_PIN, &stcGpioInit);
    GPIO_SetFunc(BSP_KEYOUT1_PORT, BSP_KEYOUT1_PIN, GPIO_FUNC_8_KEYSCAN, PIN_SUBFUNC_DISABLE);

    (void)GPIO_Init(BSP_KEYOUT2_PORT, BSP_KEYOUT2_PIN, &stcGpioInit);
    GPIO_SetFunc(BSP_KEYOUT2_PORT, BSP_KEYOUT2_PIN, GPIO_FUNC_8_KEYSCAN, PIN_SUBFUNC_DISABLE);

    PWC_Fcg0PeriphClockCmd(PWC_FCG0_KEY, Enable);

    /* Enable LRC for scan clock */
    (void)CLK_LrcCmd(Enable);

    stcKeyscanInit.u32HizCycle = KEYSCAN_HIZ_CLC_4;
    stcKeyscanInit.u32LowCycle = KEYSCAN_LOW_CLC_512;
    stcKeyscanInit.u32KeyClk   = KEYSCAN_CLK_LRC;
    stcKeyscanInit.u32KeyOut   = KEYSCAN_OUT_0T2;
    stcKeyscanInit.u32KeyIn    = (KEYSCAN_IN_8 | KEYSCAN_IN_3 | KEYSCAN_IN_7);

    (void)KEYSCAN_Init(&stcKeyscanInit);
}

/**
 * @}
 */

#endif /* BSP_EV_HC32F4A0_LQFP176 */

/**
 * @}
 */

/**
 * @}
 */

/******************************************************************************
 * EOF (not truncated)
 *****************************************************************************/
